package com.lingjtx.oss.controller;

import com.lingjtx.common.core.ResponseResult;
import com.lingjtx.common.core.constant.OSSFolderName;
import com.lingjtx.common.core.constant.ResponseTip;
import com.lingjtx.common.core.model.api.OssUploadResponseItem;
import com.lingjtx.common.core.model.api.OssUploadStream;
import com.lingjtx.common.core.util.DateTimeUtil;
import com.lingjtx.oss.common.ReactiveMinioService;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.ResponseEntity;
import org.springframework.http.codec.multipart.FilePart;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * 私有云OSS存储
 */
@RestController
@RequestMapping("/pri")
public class PriOSSController {

    private final ReactiveMinioService minioService;

    public PriOSSController(ReactiveMinioService minioService) {
        this.minioService = minioService;
    }

    /**
     * 单文件上传
     */
    @PostMapping("/upload/single")
    public Mono<ResponseResult<OssUploadResponseItem>> singleUpload(@RequestPart("file") Mono<FilePart> filePartMono,
                                                                    @RequestParam(value = "folderType", defaultValue = "0") Integer folderType) {
        return filePartMono
                .flatMap(filePart -> minioService.uploadFile(folderType, filePart))
                .map(ResponseResult::createBySuccess)
                .onErrorResume(e -> Mono.just(ResponseResult.createByError("上传失败: " + e.getMessage())));
    }

    @PostMapping("/upload/single/stream")
    public Mono<OssUploadResponseItem> singleUpload(@RequestBody OssUploadStream model) {
        if (model.getInputBytes() == null || model.getInputBytes().length == 0) {
            return Mono.just(new OssUploadResponseItem("上传文件为空", null));
        }

        String objectName = OSSFolderName.codeOf(model.getFolderType()).getFolder()
                + DateTimeUtil.getTimestamp() + model.getFileType();

        boolean isImg = minioService.isImage(model.getFileType());

        try (InputStream inputStream = new ByteArrayInputStream(model.getInputBytes())) {
            return minioService.uploadFile(objectName, inputStream, isImg);
        } catch (IOException e) {
            return Mono.just(new OssUploadResponseItem("上传异常: " + e.getMessage(), null));
        }
    }

    /**
     * 多文件上传
     */
    @PostMapping("/upload/multi")
    public Mono<ResponseResult<List<OssUploadResponseItem>>> multiUpload(@RequestPart("files") Flux<FilePart> fileParts,
                                                                         @RequestParam(value = "folderType", defaultValue = "0") Integer folderType) {
        return fileParts.flatMap(filePart -> minioService.uploadFile(folderType, filePart))
                .collectList()
                .map(ResponseResult::createBySuccess)
                .onErrorResume(e -> Mono.just(ResponseResult.createByError("上传失败: " + e.getMessage())));
    }

    /**
     * 文件预览
     */
    @GetMapping("/preview")
    public Mono<ResponseResult<String>> preview(@RequestParam("objectName") String objectName) {
        return minioService.getPreSignedUrl(objectName)
                .map(ResponseResult::createBySuccessToString);
    }

    /**
     * 批量删除
     */
    @PostMapping("/delete")
    public Mono<ResponseResult<Void>> delete(@RequestBody List<String> fileNames) {
        return minioService.delete(fileNames)
                .thenReturn(ResponseResult.createBySuccess(ResponseTip.RESPONSE_TIP_DELETE));
    }

    /**
     * 下载文件流
     */
    @GetMapping("/download")
    public Mono<ResponseEntity<Flux<DataBuffer>>> download(@RequestParam String objectName) {
        return minioService.downloadAsFlux(objectName);
    }
}